Java 设计模式之创建型模式

创建时间:2018/7/20 0:25
标签:微信
来源:http://mp.weixin.qq.com/s?__biz=MzI0MjkzMzU5OA==&mid=2247483654&idx=1&sn=625da33286fbc8f8ae020edf6b933efc&chksm=e9758b37de020221513ed55037e383f5c532c0733e2ae590400575eb4b8da556f80f7bd6c06f&mpshare=1&scene=1&srcid=0720drwsSb0SUZ970NuOA4K6#rd

Java 设计模式之创建型模式

面向对象设计有几个原则(开闭、单一等),如果能够按照这些原则来开发软件,就能充分发挥面向对象的好处(低耦合,易扩展)。设计模式正式这些原则的体现,它是前人编码过程中的经验总结,针对某些问题而提出的解决方案。

最经典的设计模式出自《设计模式-可复用面向对象软件的基础》,针对不同具体问题,书中提出了 23 个设计模式,可大致分为三类:创建型模式结构模式行为模式。

本文介绍第一大类设计模式:创建型模式。

创建型模式

单例、工厂、抽象工厂、原型、建造者

开发中会用到很多对象、最佳的使用对象的方式,是遵循面向对象的一个原则“针对接口编程”,即在程序代码中出现的对象,都是接口类型,而不要出现具体的类,创建型模式大部分都是为了解决这个问题,即:对象创建交给专门的几个类去负责,创建完之后交给用户使用,用户得到的是一个接口类型,既不必知道这些类具体是什么(只要知道它们都是某个接口的实现类),也不必知道是如何创建它们的。

1. 单例模式(Singleton)

创建唯一的一个对象

设计

classA{
   privatestatic A single=null;    
   publicstatic A getSingleton(){    
       if(null==single){            single=new A();        }        
       return single;    } }

客户端:

A a = A.getSingleton();

注意:如果是并发环境中、或者在好几个虚拟机之间创建唯一的对象,则要再用其他的方法,如并发控制、rmi 等。

2. 工厂模式(Factory)

最常见的一种模式,可在 Java 类库中大量见到,用户只需要调用工厂方法类的相应方法即可创建对象。

设计:

//Product 产品接口
interfaceProduct{}
//具体产品A
classProductAimplementsProduct{}
//Factory 工厂接口
interfaceFactory{    
   Product create(); }
classFactoryAimplementsFactory{    
   @Override    public Product create(){    
      returnnewProductA();    } }

客户端:

Factory factory = new FactoryA(); Product product = factory.create();

说明:

  1. 要修改 Product 对象的创建方式,客户端代码并不受影响

  2. 要创建另一种 Product 对象(如 ProductB ),则创建一个 Facrory 的子类 FactoryB,然后用这个对象来创建 ProductB 。虽然也修改了代码,但是仅仅限于创建 Factory 对象的地方,其他的业务逻辑部分并没有修改(业务逻辑指用到了 Product 类型的地方)

  3. 工厂方法的一种改进,叫做静态工厂方法,如果要创建另一种 Product 对象,把该过程写在工厂类的静态方法里,这在 JDK 类库里大量使用

3. 抽象工厂(Abstract Factory)

创建一组对象

上面的工厂方法其实并没有体现出好处,因为每个工厂只创建一种对象,但是如果需要创建一批对象,好处就体现出来了。抽象工厂方法适用于类似下列情形:比如要更换程序界面的显示风格,如窗口、按钮、滚动条等。如果不用抽象工厂,就得一个个对象都替换掉,这显然不简单。实际上高层业务逻辑也只是针对这些窗口或者按钮的接口进行编程,抽象工厂可以很容地把这些对象立刻换成另外一批。

设计:

//窗口对象接口
interfaceWindow{}
//某种风格A的窗口
classWindowAimplementsWindow{}
//按钮对象接口
interfaceButton{}
//某种风格A的按钮
classButtonAimplementsButton{}
//工厂接口
interfaceFactory{    
   //创建窗口    Window createWindow();    
   //创建按钮    Button createButton(); }
//生产某种风格A对象的工厂
classFactoryAimplementsFactory{
   @Override    public Window createWindow(){    
       returnnewWindowA();    }    
   @Override    public Button createButton(){    
       returnnewButtonA();    } }

客户端:

Factory facory = new FactoryA(); Window window = factory.createWindow(); Button button = factory.createButton();

4. 原型模式(Prototype)

对象可以自身复制出新的对象

适用场景:创建的对象很多属性都差不多,只需要在其他对象上修改一小部分。很多编程语言支持这种方式创建对象,比如 Java 中每个对象都有 clone ( ) 方法,那么在这样的语言里,不用专门写这种设计模式、利用自带方法即可。

设计:

classA{    
   //复制自己的实例    A clone(){} }

客户端:

A a = new A(); A b = a.clone();
//下面b可修改一些属性,成为一个新的对象

5. 建造者模式(Builder)

对象的创建其实是一个非常复杂的过程,可能需要先创建一些零件,最后再把这些零件组装起来,建造者模式把组装这个行为分离出来,使得相同的零件,可以用不同的组装方法。

设计:

/*创建一个个零件类*/
//假设A、B是零件的接口
classBuilder{  
  A createA();  
  B createB(); }
//定义零件组装过程
classDirector{    Builder builder;    Director(Builder builder){  
      this.builder = builder;        }  
   voidassembly(){        A a = builder.createA();        B b = builder.createB();        
      //下面就是根据某种方法,将a和b组装起来    } }

客户端:

Builder builder = new Builder(); Director director = new Director(builder); director.assembly();

说明:

这里的 Builder 和 Director 完全可以定义成接口,利用前面讲的工厂方法等来提供,也就是说设计模式之间是可以组合使用的,最终可以使得客户端中不存在 new 这种显示创建对象的方法。



小结

1.创建型模式是设计模式的基础,只有把这个问题解决了,上层模块才能完全对接口进行编程,想要哪个对象,直接调用某个创建型模式对象的方法就可以了。细心看上面的例子可以发现:尽管业务对象可以通过工厂类对象等创建,没有显示出现 new 关键字,但是工厂类对象本身却出现了 new 关键字。


2.有两种方法可以彻底消灭 new 

  • 把创建这些工厂类的代码聚集到一起,使变化局限于局部;

  • Java 中有反射」机制,可以把创建工厂类的方式通过配置文件来提供,这样就完全避免了修改代码,完全避免了代码中出现 new ,这是最佳的解决方案:即工厂对象由配置文件创建,业务对象由工厂对象创建。很多框架,例如 Spring ,就是采取这种方式来提供对象,它有个时髦的名字叫做「依赖注入」。